package aps.module_Machines;

//Vanilla Minecraft
import net.minecraft.src.Container;
import net.minecraft.src.EntityItem;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.ICrafting;
import net.minecraft.src.IInventory;
import net.minecraft.src.ItemStack;
import net.minecraft.src.NBTTagCompound;
import net.minecraft.src.NBTTagList;
import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.common.ISidedInventory;
import aps.module_Core.GuiIDs;
import aps.module_Core.TileEntityAPSPowered;
import aps.module_Core.module_Core.APSBlockTypes;
import buildcraft.BuildCraftCore;
import buildcraft.api.gates.Action;
import buildcraft.api.gates.IAction;
import buildcraft.api.gates.IActionReceptor;
import buildcraft.api.power.IPowerReceptor;
import buildcraft.core.IMachine;
import buildcraft.core.triggers.ActionMachineControl;
import buildcraft.core.utils.Utils;
//Forge
//Buildcraft
//APS




//Stack 0: Ingredients

public class TileEntityGrinder extends TileEntityAPSPowered implements IPowerReceptor, IInventory, ISidedInventory, IActionReceptor, IMachine
{
    private ItemStack grinderItemStacks[];
    private GrinderRecipe currentRecipe = null;
    
    public static int maxStoredPower = 1000;
    public int storedPower = 0;

    public TileEntityGrinder()
    {
        super( 0, 35, 1, 2, 0, 5, maxStoredPower, 5, maxStoredPower, APSBlockTypes.Machine);
        hasGUI = true;
        GuiID = GuiIDs.GUI_GRINDER;
        grinderItemStacks = new ItemStack[1];
    }
    
    void checkRecipe()
    {
    	if(currentRecipe == null || !currentRecipe.isIngredient(grinderItemStacks[0]))
    	{
    		currentRecipe = null;
    		for(GrinderRecipe R : module_Machines.grinderRecipes)
    		{
    			if(R.isIngredient(grinderItemStacks[0]))
    			{
    				currentRecipe = R;
    			}
    		}
    	}
    }

    public int getSizeInventory()
    {
        return grinderItemStacks.length;
    }

    public int getStartInventorySide(int side) {
    	return 0;
    }

    public int getSizeInventorySide(int side) {
	    return 1;
    }

    public ItemStack getStackInSlot(int i)
    {
        return grinderItemStacks[i];
    }

    public ItemStack decrStackSize(int i, int j)
    {
        if(grinderItemStacks[i] != null)
        {
            if(grinderItemStacks[i].stackSize <= j)
            {
                ItemStack itemstack = grinderItemStacks[i];
                grinderItemStacks[i] = null;
                checkRecipe();
                return itemstack;
            }
            ItemStack itemstack1 = grinderItemStacks[i].splitStack(j);
            if(grinderItemStacks[i].stackSize == 0)
            {
                grinderItemStacks[i] = null;
            }
            checkRecipe();
            return itemstack1;
        } else
        {
        	return null;
        }
    }

    public void setInventorySlotContents(int i, ItemStack itemstack)
    {
        grinderItemStacks[i] = itemstack;
        if(itemstack != null && itemstack.stackSize > getInventoryStackLimit())
        {
            itemstack.stackSize = getInventoryStackLimit();
        }
        checkRecipe();
    }

    public String getInvName()
    {
        return "Block Grinder";
    }
    
    public String[] getPossibleProducts()
    {
    	if (currentRecipe == null) return new String[0];
    	ItemStack[] P = currentRecipe.getAllProducts();
    	String[] Output = new String[P.length];
    	for(int i = 0; i < P.length; i++)
    		Output[i] = P[i].stackSize + " " + P[i].getItem().getItemDisplayName(P[i]) + " " + currentRecipe.chances[i] + "%";
    	return Output;
    }

    public void readFromNBT(NBTTagCompound nbttagcompound)
    {
        super.readFromNBT(nbttagcompound);
        NBTTagList nbttaglist = nbttagcompound.getTagList("Items");
        grinderItemStacks = new ItemStack[getSizeInventory()];
        for(int i = 0; i < nbttaglist.tagCount(); i++)
        {
            NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.tagAt(i);
            byte byte0 = nbttagcompound1.getByte("Slot");
            if(byte0 >= 0 && byte0 < grinderItemStacks.length)
            {
                grinderItemStacks[byte0] = ItemStack.loadItemStackFromNBT(nbttagcompound1);
            }
        }
        
        checkRecipe();
    }

    public void writeToNBT(NBTTagCompound nbttagcompound)
    {
        super.writeToNBT(nbttagcompound);
        NBTTagList nbttaglist = new NBTTagList();
        for(int i = 0; i < grinderItemStacks.length; i++)
        {
            if(grinderItemStacks[i] != null)
            {
                NBTTagCompound nbttagcompound1 = new NBTTagCompound();
                nbttagcompound1.setByte("Slot", (byte)i);
                grinderItemStacks[i].writeToNBT(nbttagcompound1);
                nbttaglist.appendTag(nbttagcompound1);
            }
        }

        nbttagcompound.setTag("Items", nbttaglist);
    }

    public int getInventoryStackLimit()
    {
        return 64;
    }

    public int getGrindProgressScaled(int i)
    {
    	int j;
    	if (canGrind())
	    	j = (int) ((storedPower / currentRecipe.getEnergyRequired()) * i);
    	else
    		j = 0;
		if(j > i) return i; else return j;
    }

    public int getBurnTimeRemainingScaled(int i)
    {
        return getGrindProgressScaled(i);
    }

    public boolean isBurning()
    {
        if (currentRecipe != null)
        	return getGrindProgressScaled((int) currentRecipe.getEnergyRequired()) > 0;
        else return false;
    }
    
    @Override
    public void updateEntity()
    {
    	super.updateEntity();
    	
    	if (worldObj.isRemote) return; 
    	
    	if(grinderItemStacks[0] == null && currentRecipe != null)
    		checkRecipe();
    	
    	if(lastMode != ActionMachineControl.Mode.Off)
        {
	    	storedPower += powerProvider.useEnergy(1, maxStoredPower - storedPower, true);
	    	if(canGrind() && storedPower >= currentRecipe.getEnergyRequired())
	        {
	        	storedPower -= currentRecipe.getEnergyRequired();
	        	grindItem();
	        }
        }
    	if(lastMode == ActionMachineControl.Mode.On) lastMode = ActionMachineControl.Mode.Off;
    }

    private boolean canGrind() {return currentRecipe != null && grinderItemStacks[0] != null && currentRecipe.getIngredient().itemID == grinderItemStacks[0].itemID;}

    public void grindItem()
    {
    	if(grinderItemStacks[0].getItem().hasContainerItem())
        {
            grinderItemStacks[0] = new ItemStack(grinderItemStacks[0].getItem().getContainerItem());
        } else
        {
            grinderItemStacks[0].stackSize -= 1; //Decrement ingredient stack
        }
        if(grinderItemStacks[0].stackSize <= 0)
        {
            grinderItemStacks[0] = null; //Remove empty stack
        }
        
        ItemStack itemstack = currentRecipe.getRandomProduct();
        if(itemstack != null)
        {
        	//Superfluous now
        	//StackUtil stackUtils = new StackUtil(itemstack.copy());
			
			ItemStack result = Utils.addToRandomInventory(itemstack, this.worldObj, this.xCoord, this.yCoord, this.zCoord, ForgeDirection.UNKNOWN);
			boolean added = false;
			
			if (result != null) {
				if (result.stackSize > 0)
					added = Utils.addToRandomPipeEntry(this,ForgeDirection.UNKNOWN, itemstack);
			}
			
			if (!added || result.stackSize == 0) {
				EntityItem entityitem = new EntityItem(worldObj, xCoord + 0.5, yCoord + 0.7, zCoord + 0.5,
						itemstack.copy());

				worldObj.spawnEntityInWorld(entityitem);
			}
        }
    }

    public boolean isUseableByPlayer(EntityPlayer entityplayer)
    {
        if(worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) != this)
        {
            return false;
        }
        return entityplayer.getDistanceSq((double)xCoord + 0.5D, (double)yCoord + 0.5D, (double)zCoord + 0.5D) <= 64D;
    }

    public void openChest() {}

    public void closeChest() {}

    @Override
	public IInventory getInventory() {return this;}
	
	public int powerRequest()
	{
		if (canGrind())
			return (int) currentRecipe.getEnergyRequired();
		else
			return 0;
	}

	@Override
	public void kill() {}

	//@Override
	//public GuiScreen getGUI(EntityPlayer entityplayer) {
	//	return new GuiGrinder(this, entityplayer.inventory);
	//}

	@Override
	public boolean isActive() { return canGrind(); }

	@Override
	public boolean manageLiquids() {return false;}

	@Override
	public boolean manageSolids() {return true;}

	@Override
	public boolean allowActions() {return true;}

	ActionMachineControl.Mode lastMode = ActionMachineControl.Mode.Unknown;
	//@Override
	public void actionActivated(Action action) {
		if (action == BuildCraftCore.actionOn) {
			lastMode = ActionMachineControl.Mode.On;
		} else if (action == BuildCraftCore.actionOff) {
			lastMode = ActionMachineControl.Mode.Off;
		} else if (action == BuildCraftCore.actionLoop) {
			lastMode = ActionMachineControl.Mode.Loop;
		}		
	}

	@Override
	public ItemStack getStackInSlotOnClosing(int var1) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void actionActivated(IAction action) {
	}

	@Override
	public int getStartInventorySide(ForgeDirection side) {
		return 0;
	}

	@Override
	public int getSizeInventorySide(ForgeDirection side) {
		return 0;
	}
	
	public boolean isPipeConnected(ForgeDirection from)
	{
		return true;
	}
	
	public void sendGUIUpdates(Container container, ICrafting iCrafting)
	{
		iCrafting.sendProgressBarUpdate(container, 0, this.storedPower);	
	}
	
	public void getGUIUpdates(int channel, int value)
	{
		this.storedPower = value;
	}
}
